<?php
/**
 * Base_App
 *
 * LICENSE
 *
 * This source file is subject to the new CC-GNU LGPL
 * It is available through the world-wide-web at this URL:
 * http://creativecommons.org/licenses/LGPL/2.1/
 *
 * @category   Base_App
 * @copyright  Copyright (c) 2009 Alexander fanatique* Thomas (me@alexander-thomas.net)
 * @license    http://creativecommons.org/licenses/LGPL/2.1/
 */
abstract class Base_App_Db_Table_Row_Validating extends Zend_Db_Table_Row_Abstract {
	private $_validation_rules = array ( ) ;
	private $_errors = array ( ) ;
	private $_log ;
	
	public function __construct ( array $config = array() ) {
		$this->_setValidationRules () ;
		$this->_log = Zend_Registry::get ( 'log' ) ;
		$this->_validation_rules [ 'on_create' ] = array();
		$this->_validation_rules [ 'on_update' ] = array();
		$this->_validation_rules [ 'on_create_and_update' ] = array();
		parent::__construct ( $config ) ;
	}
	
	/**
	 * Defines rules for validating a new or an updated object.
	 * on_create rules are validated on creation and on updating the object.
	 * on_update is skipped on creation.
	 * $this->_onCreateValidation ( 'login', 'StringLength', true, array ( 4 , 10 ) ) ;
	 * $this->_onCreateAndUpdateValidation ( 'email', 'EmailAddress', true ) ;
	 * this->_onUpdateValidation ( 'company_website', 'Hostname', false ) ;
	 */
	abstract protected function _setValidationRules ();
	
	/**
	 * Adds a validation rule for validating on creation 
	 *
	 * @param string $column Name of the column in the table
	 * @param string $method
	 * @param boolean $mandatory
	 * @param array $params Additional parameters for the selected validation method
	 */
	protected function _onCreateValidation ( $column , $method , $mandatory , array $params = array() ) {
		$this->_validation_rules['on_create'][$column][] = array('method' => $method , 'mandatory' => $mandatory , 'params' => $params);
	}
	
	/**
	 * Adds a validation rule for validating on update 
	 *
	 * @param string $column Name of the column in the table
	 * @param string $method
	 * @param boolean $mandatory
	 * @param array $params Additional parameters for the selected validation method
	 */
	protected function _onUpdateValidation ( $column , $method , $mandatory , array $params = array() ) {
		$this->_validation_rules [ 'on_update' ] [ $column ] [] = array ( 'method' => $method , 'mandatory' => $mandatory , 'params' => $params ) ;
	}
	
	/**
	 * Adds a validation rule for validating on creation and on update 
	 *
	 * @param string $column Name of the column in the table
	 * @param string $method
	 * @param boolean $mandatory
	 * @param array $params Additional parameters for the selected validation method
	 */
	protected function _onCreateAndUpdateValidation ( $column , $method , $mandatory , array $params = array() ) {
		$this->_validation_rules [ 'on_create_and_update' ] [ $column ] [] = array ( 'method' => $method , 'mandatory' => $mandatory , 'params' => $params ) ;
	}
	
	/**
	 * Getter for all validation rules for a column
	 *
	 * @param string $column Name of the current column
	 * @param string $mode May be on_create or on_update. on_create_and_update will be automatically sent
	 * @return array
	 */
	protected function _getValidationRulesForColumn ( $column , $mode ) {
		return @array_merge((array) $this->_validation_rules [ $mode ] [ $column ], (array) $this->_validation_rules [ 'on_create_and_update' ] [ $column ]) ;
	}
	
	/**
	 * Validates a rule against the current value which is saved for this column.
	 *
	 * @param string $column Name of the table column
	 * @param string $method Validation method
	 * @param boolean $mandatory 
	 * @param array $params Additional parameters for the selected validation method
	 */
	protected function _validateRule ( $column , $method , $mandatory , array $params = array() ) {
		$this->_log->info($column." ".$this->$column." ".$method);
		$value = str_replace ( " ", "", $this->$column ) ;
		if (true === $mandatory || ! empty ( $value )) {
			if($method === 'Confirmation'){
				$tmp = $column.'_'.strtolower($method);
				$params = array($this->$tmp);
			}
			if (false === Zend_Validate::is ( $value, $method, $params )) {
				$this->_log->info ( 'Added $errors: ' . $column ) ;
				$this->_errors [] = $column;
				$this->_errors = array_unique($this->_errors);
			}
		}
	}
	
	/**
	 * Validates all on_create rules for this object.
	 * @throws Base_App_Validation_Exception
	 * @string $mode May be either 'on_create' or 'on_update'
	 */
	protected function _validate($mode){
		$this->_log->info ( '_validate(' . $mode . ')' ) ;
		$info = $this->getTable()->info();
		$rules = array();
		foreach($info['cols'] as $col) {
			$rules = $this->_getValidationRulesForColumn ( $col, $mode ) ;
			foreach ( $rules as $rule ) {
				$this->_validateRule ( $col, $rule [ 'method' ], $rule [ 'mandatory' ], $rule [ 'params' ] ) ;
			}
		}
		if (count($this->_errors) > 0) {
			$this->_log->err ( 'Validation of new row failed. Errors: ' . print_r ( $this->_errors, true ) ) ;
			throw new Base_App_Validation_Exception( $this->_errors ) ;
		}
	}
	
	/**
	 * This method is called before the process of inserting a new row into the database. 
	 */
	protected function _insert () {
		$this->_log->info ( '_insert()' ) ;
		$this->_validate ( 'on_create' ) ;
	}
	
	/**
	 * This method is called before the process of updating a row of the database. 
	 */
	protected function _update () {
		$this->_log->info ( '_update()' ) ;
		$this->_validate ( 'on_update' ) ;
	}
}
?>
